package com.yunsc.store.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yunsc.common.exception.YunscException;
import com.yunsc.common.utils.PageResult;
import com.yunsc.media.service.YunscUploadFileService;
import com.yunsc.store.dao.YunscUserDao;
import com.yunsc.store.dto.QueryUserParamsDTO;
import com.yunsc.store.dto.UserBalanceDTO;
import com.yunsc.store.dto.UserParamsDTO;
import com.yunsc.store.entity.YunscUserBalanceLogEntity;
import com.yunsc.store.entity.YunscUserEntity;
import com.yunsc.store.entity.YunscUserGradeLogEntity;
import com.yunsc.store.entity.YunscUserPointsLogEntity;
import com.yunsc.store.service.*;
import com.yunsc.system.vo.UserAssetsVO;
import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.math.BigDecimal;

import static com.yunsc.common.utils.DateUtils.convertStringToSeconds;


@Service("yunscUserService")
public class YunscUserServiceImpl extends ServiceImpl<YunscUserDao, YunscUserEntity> implements YunscUserService {

    @Resource
    private YunscUserCouponService userCouponService;
    @Resource
    private YunscUserPointsLogService userPointsLogService;
    @Resource
    private YunscUserBalanceLogService userBalanceLogService;
    @Resource
    private YunscUploadFileService uploadFileService;
    @Resource
    private YunscUserGradeLogService userGradeLogService;


    @Override
    @Transactional
    public void orderRefundMoney(String orderNo, String refundMoney, Integer refundPoints, Integer userId) {
        YunscUserEntity user = this.getById(userId);
        if (user == null){
            throw new YunscException("用户不存在");
        }
        user.setBalance(String.valueOf(new BigDecimal(user.getBalance()).add(new BigDecimal(refundMoney))));
        user.setPoints(user.getPoints() + refundPoints);
        this.updateById(user);
        //  记录余额流水日志
        userBalanceLogService.addUserBalanceLog(userId, 40, "", "订单退款返还余额",refundMoney, user.getStoreId());
        //  记录积分流水日志
        userPointsLogService.addPointsLog(userId, refundPoints, "订单退款返还积分", user.getStoreId());
    }

    @Override
    public YunscUserEntity queryUserInfo(Integer userId) {
        YunscUserEntity user = this.baseMapper.selectUserInfo(userId);
        if (user == null){
            throw new YunscException("用户不存在");
        }
        user.setAvatarUrl(uploadFileService.queryFileUrlById(user.getAvatarId()));
        return user;
    }

    @Override
    public UserAssetsVO queryUserAssets(Integer userId) {

        YunscUserEntity user = this.getById(userId);
        if (user == null){
            throw new YunscException("用户不存在");
        }
       int couponCount = userCouponService.queryUserCoupon(userId);
        return UserAssetsVO.builder()
                .balance(user.getBalance())
                .points(user.getPoints())
                .coupon(couponCount)
                .build();
    }

    @Override
    public void subtractPoints(Integer userId, int pointsNum, String msg) {
        YunscUserEntity user = this.getById(userId);
        if (user == null){
            throw new YunscException("用户不存在");
        }

        if (user.getPoints() < pointsNum) {
            throw new YunscException("积分不足");
        }
        user.setPoints(user.getPoints() - pointsNum);
        this.updateById(user);

        // 记录积分流水日志
        userPointsLogService.addPointsLog(userId, -pointsNum, msg, user.getStoreId());

    }

    @Override
    public void updateUserPoints(Integer userId, Integer pointsNum, String msg) {
        YunscUserEntity user = this.getById(userId);
        if (user == null) {
            throw new YunscException("用户不存在");
        }
        user.setPoints(user.getPoints() + pointsNum);
        this.updateById(user);
        // 记录积分流水日志
        userPointsLogService.addPointsLog(userId, pointsNum, msg, user.getStoreId());

    }

    @Override
    public PageResult<YunscUserEntity> queryUserList(QueryUserParamsDTO param, Integer storeId) {
        String betweenTimeStart = param.getBetweenTimeStart();
        String betweenTimeEnd = param.getBetweenTimeEnd();
        if (StringUtils.isNotEmpty(betweenTimeStart) && StringUtils.isNotEmpty(betweenTimeEnd)){
            long start = convertStringToSeconds(betweenTimeStart);
            long end = convertStringToSeconds(betweenTimeEnd);
            param.setBetweenTimeStart(String.valueOf(start));
            param.setBetweenTimeEnd(String.valueOf(end));
        }
        Page<YunscUserEntity> page = this.baseMapper.selectUserPage(new Page<>(param.getPage(), param.getPageSize()), param, storeId);

        if (!CollectionUtils.isEmpty(page.getRecords())){
            page.getRecords().forEach(user -> {
                if (user.getAvatarId() != null && user.getAvatarId() > 0){
                    user.setAvatarUrl(uploadFileService.queryFileUrlById(user.getAvatarId()));
                }
            });
        }

        return PageResult.formatPageResult(page.getRecords(), param.getPage(), param.getPageSize(), page.getTotal());
    }

    @Override
    @Transactional
    public void editUserBalance(UserBalanceDTO param) {
        Integer userId = param.getUserId();
        YunscUserEntity user = this.getById(userId);
        if (user == null){
            throw new YunscException("用户不存在");
        }
        String target = param.getTarget();

        if ("balance".equals(target)) {
            BigDecimal userBalance = new BigDecimal(user.getBalance());
            UserBalanceDTO.Balance balanceForm = param.getForm().getBalance();
            switch (balanceForm.getMode()) {
                case "inc":
                    user.setBalance(String.valueOf(userBalance.add(new BigDecimal(balanceForm.getMoney()))));
                    break;
                case "dec":
                    BigDecimal subtract = userBalance.subtract(new BigDecimal(balanceForm.getMoney()));
                    BigDecimal decimal = subtract.compareTo(BigDecimal.ZERO) >= 0 ? subtract : BigDecimal.ZERO;
                    user.setBalance(String.valueOf(decimal));
                    break;
                case "final":
                    user.setBalance(balanceForm.getMoney());
                    break;
                default:
                    throw new IllegalArgumentException("Invalid mode for balance operation");
            }

            YunscUserBalanceLogEntity balanceLog = createBalanceLog(balanceForm, userId, user.getStoreId());
            boolean success = userBalanceLogService.save(balanceLog);
            if (!success) {
                throw new YunscException("更新用户余额日志失败");
            }

        } else if ("points".equals(target)) {
            UserBalanceDTO.Points pointsForm = param.getForm().getPoints();
            int pointsValue = pointsForm.getValue();

            switch (pointsForm.getMode()) {
                case "inc":
                    user.setPoints(user.getPoints() + pointsValue);
                    break;
                case "dec":
                    user.setPoints(Math.max(user.getPoints() - pointsValue, 0)); // 防止负数
                    break;
                case "final":
                    user.setPoints(pointsValue);
                    break;
                default:
                    throw new IllegalArgumentException("Invalid mode for points operation");
            }

            YunscUserPointsLogEntity pointsLog = createUserPointsLog(pointsForm, userId, user.getStoreId());
            boolean saved = userPointsLogService.save(pointsLog);
            if (!saved) {
                throw new YunscException("更新用户积分日志失败");
            }

        } else {
            throw new YunscException("Unsupported target");
        }

        boolean updated = this.updateById(user);
        if (!updated) {
            throw new YunscException("更新用户信息失败");
        }
    }

    @Override
    @Transactional
    public void editUserGrade(UserParamsDTO param) {
        Integer userId = param.getUserId();
        YunscUserEntity userEntity = this.getById(userId);
        if (userEntity == null){
            throw new YunscException("用户不存在");
        }
        userEntity.setGradeId(param.getForm().getGradeId());
        // 更新用户等级信息
        boolean update = this.updateById(userEntity);
        if (!update){
            throw new YunscException("修改用户等级失败");
        }

        // 记录更新日志
        YunscUserGradeLogEntity userGradeLog = new YunscUserGradeLogEntity();
        userGradeLog.setOldGradeId(userEntity.getGradeId());
        userGradeLog.setUserId(userId);
        userGradeLog.setRemark(param.getForm().getRemark());
        userGradeLog.setNewGradeId(param.getForm().getGradeId());
        // 变更类型(10后台管理员设置 20自动升级)
        userGradeLog.setChangeType(10);
        userGradeLog.setStoreId(userEntity.getStoreId());
        boolean save = userGradeLogService.save(userGradeLog);
        if (!save){
            throw new YunscException("修改用户等级失败");
        }
    }

    @Override
    public void deleteUser(Integer userId) {
        boolean update = this.update(new UpdateWrapper<YunscUserEntity>()
                .eq("user_id", userId).set("is_delete", 1));
        if (!update){
            throw new YunscException("删除用户失败");
        }
    }

    @Override
    public int queryUserTotalCount(int startInSeconds, int endInSeconds, Integer currentStoreId) {
        LambdaQueryWrapper<YunscUserEntity> queryWrapper = new LambdaQueryWrapper<YunscUserEntity>()
                .eq(YunscUserEntity::getStoreId, currentStoreId)
                .eq(YunscUserEntity::getIsDelete, 0);
        if (startInSeconds > 0 && endInSeconds > 0) {
            queryWrapper.between(YunscUserEntity::getCreateTime, startInSeconds, endInSeconds);
        }
        return this.count(queryWrapper);
    }

    private YunscUserBalanceLogEntity createBalanceLog(UserBalanceDTO.Balance balanceForm, Integer userId, Integer storeId) {
        YunscUserBalanceLogEntity log = new YunscUserBalanceLogEntity();
        log.setMoney(balanceForm.getMode().startsWith("dec") ? "-" + balanceForm.getMoney() : balanceForm.getMoney());
        log.setUserId(userId);
        log.setScene(30);
        log.setDescribe("后台管理员操作");
        log.setRemark(balanceForm.getRemark());
        log.setStoreId(storeId);
        return log;
    }

    private YunscUserPointsLogEntity createUserPointsLog(UserBalanceDTO.Points pointsForm, Integer userId, Integer storeId) {
        YunscUserPointsLogEntity log = new YunscUserPointsLogEntity();
        log.setValue(pointsForm.getMode().startsWith("dec") ? -pointsForm.getValue() : pointsForm.getValue());
        log.setUserId(userId);
        log.setDescribe("后台管理员操作");
        log.setRemark(pointsForm.getRemark());
        log.setStoreId(storeId);
        return log;
    }


}